home *** CD-ROM | disk | FTP | other *** search
/ BMUG Revelations / BMUG Revelations.toast / Utilities / Random / Commodore 64c / SOURCE / VIC.c < prev   
Text File  |  1994-03-15  |  8KB  |  273 lines

  1. /*
  2.     Commodore 64 Emulator v0.1      Earle F. Philhower III 
  3.     Copyright (C) 1993-4            (st916w9r@dunx1.ocs.drexel.edu)
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include "Memory.h"
  20. #include "MemoryCalls.h"
  21. #include "Error.h"
  22. void TotalRedrawVIC(void);
  23.  
  24.  
  25. #define FastDraw(a, b, c) \
  26. { \
  27.     thisLine=(char**)&(lineStart[(word)((a)<<3)]); \
  28.     theseDefs=(char*)(VICCharDefs+(word)((c)<<3)); \
  29.     *(*thisLine++ + b)=*theseDefs++; \
  30.     *(*thisLine++ + b)=*theseDefs++; \
  31.     *(*thisLine++ + b)=*theseDefs++; \
  32.     *(*thisLine++ + b)=*theseDefs++; \
  33.     *(*thisLine++ + b)=*theseDefs++; \
  34.     *(*thisLine++ + b)=*theseDefs++; \
  35.     *(*thisLine++ + b)=*theseDefs++; \
  36.     *(*thisLine++ + b)=*theseDefs++; \
  37. }
  38.  
  39.  
  40.  
  41. WindowPtr VICWind;
  42. byte VICText[1024], VICRegister[0x2f];
  43. word VICAddrBase, VICScreenPage, VICCharBase;
  44. byte VICBank, *VICCharDefs;
  45. byte *lineStart[200];
  46.  
  47. Rect fullRect, leftRect, rightRect, topRect, botRect, spr;
  48. BitMap saveMap, spriteMap, VICMap, fullMap;
  49.  
  50. GrafPtr spriteGraf;
  51.  
  52. byte CreateOffscreenBitMap(GrafPtr *newOffscreen, Rect *inBounds)
  53. {
  54.     GrafPtr savePort, newPort;
  55.  
  56.     GetPort(&savePort);
  57.     newPort = (GrafPtr)GetMemory(sizeof(GrafPort));
  58.  
  59.     OpenPort(newPort);
  60.  
  61.     newPort->portRect = *inBounds;
  62.     newPort->portBits.bounds = *inBounds;
  63.     RectRgn(newPort->clipRgn, inBounds);
  64.     RectRgn(newPort->visRgn, inBounds);
  65.  
  66.     newPort->portBits.rowBytes =
  67.         ((inBounds->right - inBounds->left + 15) >> 4) << 1;
  68.     newPort->portBits.baseAddr = (Ptr)
  69.         GetMemory(newPort->portBits.rowBytes*(long)(inBounds->bottom-inBounds->top));
  70.         
  71.     if(MemError() != noErr) {
  72.         SetPort(savePort);
  73.         ClosePort(newPort);
  74.         DisposPtr((Ptr)newPort);
  75.         return 0;}
  76.  
  77.     EraseRect(inBounds);
  78.     *newOffscreen = newPort;
  79.     SetPort(savePort);
  80.     return 1;
  81. }
  82.  
  83. Ptr NewBitMap(BitMap *theBits, Rect *rp)
  84. {
  85.     theBits->rowBytes=((rp->right-rp->left+15)/16)*2;
  86.     theBits->baseAddr=(Ptr)GetMemory(theBits->rowBytes*(rp->bottom-rp->top));
  87.     theBits->bounds=*rp;
  88.     return(theBits->baseAddr);
  89. }
  90.  
  91. int VICInitialize()
  92. {
  93.     int row, col, chr;
  94.  
  95.     row=col=0;
  96.     SetRect(&fullRect,0,0,320,200);
  97.     SetRect(&leftRect,0,0,7,200);
  98.     SetRect(&rightRect,320-8,0,320,200);
  99.     SetRect(&topRect,0,0,320,4);
  100.     SetRect(&botRect,0,200-4,320,200);
  101.     SetRect(&spr,0,0,24,21);
  102.     VICWind=GetNewWindow(128,nil,(void *)-1L);
  103.     if (VICWind==nil) return(kWindowMissing);
  104.     ShowWindow(VICWind);
  105.     SetPort(VICWind);
  106.     SelectWindow(VICWind);
  107.     if (NewBitMap(&spriteMap, &spr)==0) return kOutOfMemory;
  108.     if (NewBitMap(&VICMap, &fullRect)==0) return kOutOfMemory;
  109.     if (NewBitMap(&fullMap, &fullRect)==0) return kOutOfMemory;
  110.  
  111.     for (row=0; row<200; row++)
  112.         lineStart[row]=(byte *)VICMap.baseAddr+40*row;
  113.  
  114.     return(kNoError);
  115. }
  116.  
  117. void VICAddrAdjust()
  118. {
  119.     VICBank=(RAM[0xdd00]&3)^3;
  120.     VICAddrBase=VICBank*16384;
  121.     VICScreenPage=((RAM[0xd018]&0xf0)>>4)*0x0400+VICAddrBase;
  122.     VICCharBase=((RAM[0xd018]&0x0e)*1024);
  123.     if ((VICBank==1)||(VICBank==3))
  124.         VICCharDefs=RAM+(VICAddrBase+VICCharBase);
  125.     else 
  126.         if (VICCharBase==4096) VICCharDefs=charROM;
  127.         else if (VICCharBase==6144) VICCharDefs=charROM+0x0800;
  128.         else VICCharDefs=RAM+(VICAddrBase+VICCharBase);
  129. }
  130.  
  131. byte NotSameVIC()
  132. {
  133.     register byte addr;
  134.     
  135.     for (addr=0; addr<0x2f; addr++) {
  136.         if (addr==0x11)
  137.         {    if ((RAM[0xd011]&127)!=(VICRegister[0x11]&127))
  138.             return 1;}
  139.         else if (addr==0x12);
  140.         else if (RAM[0xd000+addr]!=VICRegister[addr]) return 1; }
  141.     return 0;
  142. }
  143.  
  144. void DrawSprites()
  145. {
  146.     byte spriteNum, row, *spb0, *spb1, *spb2;
  147.     word xpos, ypos, addr0, addr1, addr2;
  148.     Rect t;
  149.     
  150.     BlockMove(VICMap.baseAddr, fullMap.baseAddr, GetPtrSize(VICMap.baseAddr));
  151.     saveMap = qd.thePort->portBits;
  152.     SetPortBits(&spriteMap);
  153.     for (spriteNum=0; spriteNum<8; spriteNum++)
  154.         if (VICRegister[0x15]&(1<<spriteNum)) {
  155.             xpos=VICRegister[0x00+spriteNum*2]-24;
  156.             ypos=VICRegister[0x01+spriteNum*2]-50;
  157.             xpos += (VICRegister[0x10]&(1<<spriteNum))?256:0;
  158.             t.top=ypos;t.left=xpos;
  159.             t.right=t.left+24+((VICRegister[0x1d]&(1<<spriteNum))?24:0);
  160.             t.bottom=t.top+21+((VICRegister[0x17]&(1<<spriteNum))?21:0);
  161.             addr0 = VICAddrBase+RAM[VICScreenPage+1016+spriteNum]*64;
  162.             addr1= addr0+1; addr2=addr0+2;
  163.             spb0=(byte *)spriteMap.baseAddr; spb1=spb0+1; spb2=spb0+2;
  164.             for (row=0; row<21; row++) {
  165.                 spb0[row<<2]=RAM[addr0+row*3];
  166.                 spb1[row<<2]=RAM[addr1+row*3];
  167.                 spb2[row<<2]=RAM[addr2+row*3]; }
  168.             CopyBits(&spriteMap,&fullMap,&spr,&t,srcOr,nil); }
  169.     SetPortBits(&saveMap);
  170.     SetPort(VICWind);
  171. }
  172. /*
  173. void ScrollScreen()
  174. {
  175.     word xscroll, yscroll;
  176.     
  177.     xscroll=VICRegister[0x16]&7; yscroll=(VICRegister[0x11]&7)-3;
  178.     if (yscroll>0)
  179.         BlockMove(lineStart[0],lineStart[yscroll],(320/8)*(200-yscroll));
  180.     else if (yscroll<0)
  181.         BlockMove(line
  182. */    
  183. void DrawTextScreen(byte total)
  184. {
  185.     word chr;
  186.     byte row, col;
  187.     register char **thisLine;
  188.     register char *theseDefs;
  189.     
  190.     row=col=0;
  191.     saveMap=qd.thePort->portBits;
  192.     SetPortBits(&VICMap);
  193. /*    SetOrigin(-(VICRegister[0x16]&7),-((VICRegister[0x11]&7)-3));*/
  194.     if (VICRegister[0x11]&32) {
  195.         VICCharDefs=RAM+VICAddrBase+((VICRegister[0x18]&8)?8192:0);
  196.         for (chr=0;chr<1000;chr++) {
  197.             FastDraw(row,col,chr);
  198.             col++;if (col>39) {col=0;row++;} }
  199.         }
  200.     else {
  201.         if (total)
  202.             for (chr=0;chr<1000;chr++) {
  203.                 FastDraw(row,col,RAM[chr+VICScreenPage]);
  204.                 VICText[chr]=RAM[chr+VICScreenPage];
  205.                 col++;if (col>39) {col=0;row++;} }
  206.         else
  207.             for (chr=0;chr<1000;chr++) {
  208.                 if (VICText[chr]!=RAM[chr+VICScreenPage]) {
  209.                     FastDraw(row,col,RAM[chr+VICScreenPage]);
  210.                     VICText[chr]=RAM[chr+VICScreenPage]; }
  211.                 col++;if (col>39) {col=0;row++;} } }
  212. /*    SetOrigin(0,0);*/
  213.     SetPortBits(&saveMap);
  214. /*    ScrollRect(&fullRect, VICRegister[0x16]&7,(VICRegister[0x11]&7)-3,nil);*/
  215. }
  216.  
  217. void DrawBorders()
  218. {
  219.     saveMap=qd.thePort->portBits;
  220.     SetPortBits(&VICMap);
  221.     if (VICRegister[0x16]&8);else {FillRect(&leftRect,(PatPtr)&qd.black);FillRect(&rightRect,(PatPtr)&black);}
  222.     if (VICRegister[0x11]&8);else {FillRect(&botRect,(PatPtr)&black);FillRect(&topRect,(PatPtr)&black);}
  223.     SetPortBits(&saveMap);
  224. }
  225.  
  226. void CopyTextToScreen()
  227. {
  228.     SetPort(VICWind);
  229.     CopyBits(&VICMap,&(VICWind->portBits),&fullRect,&fullRect,srcCopy,nil);
  230. }
  231.  
  232. void CopySpritesToScreen()
  233. {
  234.     SetPort(VICWind);
  235.     CopyBits(&fullMap,&(VICWind->portBits),&fullRect,&fullRect,srcCopy,nil);    
  236. }
  237.  
  238. void BlankScreen()
  239. {
  240.     saveMap = qd.thePort->portBits;
  241.     SetPortBits(&VICMap);
  242.     FillRect(&fullRect, (PatPtr)&qd.gray);
  243.     SetPortBits(&saveMap);
  244.     CopyTextToScreen();
  245.     return;
  246. }
  247.  
  248. void RedrawVIC()
  249. {
  250.     if (NotSameVIC()) { TotalRedrawVIC(); return; }
  251.     VICAddrAdjust();
  252.     SetPort(VICWind);
  253.     if (VICRegister[0x11]&16); else { BlankScreen(); return;}
  254.     DrawTextScreen(0);
  255.     DrawBorders();
  256.     if (VICRegister[0x15]) { DrawSprites(); CopySpritesToScreen();}
  257.     else CopyTextToScreen();
  258. }
  259.  
  260. void TotalRedrawVIC()
  261. {
  262.     register byte addr;
  263.  
  264.     for (addr=0; addr<0x2f; addr++) VICRegister[addr]=RAM[0xd000+addr];
  265.     VICAddrAdjust();
  266.     SetPort(VICWind);    
  267.     if (VICRegister[0x11]&16); else { BlankScreen(); return;}
  268.     DrawTextScreen(1);
  269.     DrawBorders();
  270.     if (VICRegister[0x15]) { DrawSprites(); CopySpritesToScreen();}
  271.     else CopyTextToScreen();
  272. }
  273.